package accesslog

import (
	"bytes"
	"gitee.com/chicken-c/go-learn/webook/pkg/logger"
	"github.com/gin-gonic/gin"
	"io"
	"time"
)

type Builder struct {
	l logger.Logger
}

func NewBuilder(l logger.Logger) *Builder {
	return &Builder{l: l}
}

func (b *Builder) Build() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		start := time.Now()

		var ac AccessLog
		ac.Method = ctx.Request.Method
		url := ctx.Request.URL.String()
		if len(url) > 1024 {
			url = url[:1024]
		}
		ac.Url = url

		body, _ := ctx.GetRawData()
		ctx.Request.Body = io.NopCloser(bytes.NewReader(body))
		if len(body) > 1024 {
			body = body[:1024]
		}
		ac.ReqBody = string(body)

		//传入我们自己的Writer
		ctx.Writer = &responseWriter{
			al:             &ac,
			ResponseWriter: ctx.Writer,
		}
		defer func() {
			ac.Duration = time.Since(start).String()
			b.l.Debug("http", logger.Field{
				Key: "req",
				Val: ac,
			})
		}()

		//执行下一个middleware,最后会回到这里，我们需要打印响应
		ctx.Next()
	}
}

type AccessLog struct {
	Method     string
	Url        string
	Duration   string
	ReqBody    string
	RespBody   string
	StatusCode int
}

// 装饰器模式
type responseWriter struct {
	al *AccessLog
	gin.ResponseWriter
}

// WriteString writes the string into the response body.
func (w *responseWriter) WriteString(data string) (int, error) {
	w.al.RespBody = data
	return w.ResponseWriter.WriteString(data)
}

func (w *responseWriter) WriteHeader(statusCode int) {
	w.al.StatusCode = statusCode
	w.ResponseWriter.WriteHeader(statusCode)
}

func (w *responseWriter) Write(data []byte) (int, error) {
	w.al.RespBody = string(data)
	return w.ResponseWriter.Write(data)
}
